﻿/*
 * Twipler - Twitter Web Client with features.
 *  
 *  Copyright (C) 2009, 2010. Ian Quigley
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details. 
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Twipler;
using Twipler.App.Machine;
using Twipler.App.Machine.Instructions;
using Twipler.App.Parse.Code;
using Twipler.App.Render.Tree;
using Xunit;

namespace UnitTests.App.Parse
{
    public class ArrangeCodeParser
    {
        private readonly Instruction[] _program;

        public ArrangeCodeParser(Instruction[] program)
        {
            _program = program;
        }

        public ArrangeCodeParser(List<Instruction> program)
        {
            _program = program.ToArray();
        }

        public string Test
        {
            get { return CreateTest(new StringBuilder()); }
        }

        public string CreateTest(StringBuilder html)
        {
            if ((_program != null) && (_program.Count() > 0))
                foreach (Instruction inst in _program)
                    BuildTest(html, inst);

            return html.ToString();
        }

        public void BuildTest(StringBuilder html, Instruction inst)
        {
            string typename = inst.GetType().ToString();

            html.AppendFormat("{0} ", typename.Substring(typename.LastIndexOf('.') + 1));

            if (inst is Call)
            {
                StaticMethodCall emc = Helper.GetPrivateField(inst, "_call") as StaticMethodCall;
                if (emc != null)
                {
                    ArrangeEntityMethodCallParser p = new ArrangeEntityMethodCallParser(emc);
                    html.AppendFormat(p.Test);
                }
                else
                {
                    html.AppendFormat("{0} ", Helper.GetPrivateField(inst, "_methodName"));
                }
            }

            if (inst is Declare)
            {
                Variable var = Helper.GetPrivateField(inst, "_variable") as Variable;
                html.AppendFormat("{0} {1} ", var.Type.ToString().Substring("System.".Length), var.Name);
            }

            if (inst is BranchInstruction)
                html.AppendFormat("{0} ", ((BranchInstruction)inst).Name);

            if (inst is PopV)
                html.AppendFormat("{0} ", Helper.GetPrivateField(inst, "_varname"));

            if (inst is PushI)
                html.AppendFormat("{0} ", Helper.GetPrivateField(inst, "val"));

            if (inst is PushV)
                html.AppendFormat("{0} ", Helper.GetPrivateField(inst, "_varname"));
        }

        private bool AreSameLength(List<Instruction> result)
        {
            return ((result != null) && (result.Count == _program.Count()));
        }

        private Instruction InstructionAt(int index)
        {
            if ((index < 0) || (index >= _program.Count()))
                return null;

            return _program[index];
        }

        public void AssertSame(List<Instruction> expected)
        {
            Assert.True(AreSameLength(expected));

            for (int i = 0; i < expected.Count; i++)
                Assert.IsType(InstructionAt(i).GetType(), expected[i]);
        }
    }
}
